Skip to main content

Uso de la interfaz de scripting de Git

CODESYS Git proporciona una interfaz de scripting para Git. A continuación se muestran ejemplos de cómo usar la interfaz. A continuación también encontrarás información sobre la salida en texto de los mensajes generados por muchas operaciones de Git

Para más información, ver: Documentación de la API del motor de secuencias de comandos

Requerimientos

Para ejecutar los ejemplos siguientes, es necesario lo siguiente:

  • CODESYS 3.5.19.30 o superior

También se requieren los siguientes componentes:

  • CODESYS Library Documentation Support (para crear la biblioteca compilada)

  • CODESYS Git 1.6.0.0 o superior

  • Una instalación local de Git

Importante

Utilice contraseñas de SecureString siempre que sea posible

Para aumentar la seguridad, las contraseñas deben pasarse como SecureString de.NET.

Las operaciones de GIT afectadas son: clone, fetch, pull, push

SecureStrings se puede crear en IronPython de la siguiente manera. La «contraseña» en sí misma debe provenir de una cadena segura y no, como aquí se muestra a modo de demostración, estar en texto plano en el script. Internamente, cada contraseña proporcionada se maneja de forma segura

        from System.Security import SecureString 

        sec_str_password = SecureString()
        for c in "Passwort":    
            sec_str_password.AppendChar(c)

Para más medidas de seguridad al usar CODESYS Git consulte: Seguridad para CODESYS Git

Preparación

CODESYS biblioteca

Porque no CODESYS las bibliotecas se administran actualmente en Git, las fuentes de un CODESYS la biblioteca es obligatoria. String Functions.library biblioteca del CODESYS String Libraries el producto se usa en los ejemplos.

Repositorio remoto de Git

Para este ejemplo, se usa un repositorio Git simple en el sistema de archivos como repositorio remoto.

Para prepararlo, primero borre el directorio correspondiente y, a continuación, cree uno nuevo.

import shutil
import os 

def prepare_empty_dir(empty_dir_path):
    print("Prepare empty directory at", empty_dir_path)
    shutil.rmtree(empty_dir_path, ignore_errors=True)
    if not(os.path.exists(empty_dir_path) and os.path.isdir(empty_dir_path)):
        os.makedirs(empty_dir_path)

A continuación, se crea un repositorio Git vacío.

import subprocess
def create_bare_git_repository(bare_repository_path):
    print("Create bare git repository at", bare_repository_path)
    create_bare_repository_cmd = 'cmd /c "git -C \"' + bare_repository_path + '\" init --bare"'
    try:
        retcode = subprocess.call(create_bare_repository_cmd, shell=True)
        if retcode < 0:
            raise Exception("Creating bare git repository at " + bare_repository_path + " failed: ", -retcode)
        else:
            print("Creating bare git repository at " + bare_repository_path + " succeeded.")
    except Exception as e:
        print("[ERROR] Creating bare git repository failed: ", e)
        raise

El repositorio vacío de Git se llena con el contenido del CODESYS biblioteca.

def initialize_bare_git_repository(library_path, local_repository_path, bare_repository_path):
    print("Open library:", library_path)
    project = projects.open(library_path)
     
    print("Initiate local git repository")
    project.git.init(local_repository_path)
    project.git.commit_complete("Create git repo for lib", "user", "mail@mail")
     
    print("Push to remote git repository")
    origin_remote = project.git.remote_add("origin", bare_repository_path)
    project.git.branch_set_upstream_to(origin_remote)
    project.git.push()
    project.git.de_init(cleanUpFileSystem=True)
    project.close()

El siguiente script ejecuta las funciones descritas.

import os

def main():
    if projects.primary:
        projects.primary.close()

    basepath = "C:\\CODESYS_Projects\\Git_Scripting_Tutorial\\"

    project_basepath = os.path.join(basepath, "projects\\")
    library_file_name = "ExampleLib1.library"
    library_path = os.path.join(project_basepath, library_file_name)

    remote_repo_basepath = os.path.join(basepath, "remotes\\")
    remote_repo_directory_name = "ExampleLib1RemoteRepo"
    remote_repo_path = os.path.join(remote_repo_basepath, remote_repo_directory_name)

    local_repo_basepath = os.path.join(basepath, "repos\\")
    local_repo_directory_name = "ExampleLib1LocalRepo"
    local_repo_path = os.path.join(local_repo_basepath, local_repo_directory_name)

    print("Create and push library to remote git repository")
    
    prepare_empty_dir(remote_repo_path)
    create_bare_git_repository(remote_repo_path)
    initialize_bare_git_repository(library_path, local_repo_path, remote_repo_path)

    print("[Success] All done")


if __name__ == '__main__':
    main()

El repositorio Git simple creado de esta manera y provisto de contenido se usa para los demás ejemplos.

Clonación de un repositorio Git remoto

Se ejecuta la siguiente función git clone para un repositorio Git remoto.

def clone_git_repository(project_basepath, project_file_name, remote_repo_url_or_path, local_repo_path):
    update_flags = VersionUpdateFlags.UpdateAll | VersionUpdateFlags.SilentMode    
    project = git.clone(project_basepath, project_file_name, remote_repo_url_or_path, local_repo_path, update_flags=update_flags)
    project.save()
    return project

Creación y fusión de una nueva sucursal

La siguiente función auxiliar crea algunos objetos nuevos en un CODESYS proyecto como ejemplo.

def add_dut(project):
    ST_STRUCT_STR = """\
        a : BOOL;
        b : BIT;
        c : BIT;
    """

    ST_UNION_STR = """\
    TYPE ExampleUnion :
    UNION
        Zahl : INT;
        Prozent : ExampleAlias;
        Bits : ExampleStruct;
    END_UNION
    END_TYPE
    """

   # Create a struct DUT and insert the list of variables just into the right
   # place in line two, row 0 (line numbering starts with line 0)
   example_dut_struct = project.create_dut('ExampleStruct') # DutType.Structure is the default
   example_dut_struct.textual_declaration.insert(2, 0, ST_STRUCT_STR) 

   # Alias types get their "content" via the base type, which will just end up 
   # as one line in the declaration part:    
   # TYPE MyAlias : INT (0..100); END_TYPE 
   example_dut_alias = project.create_dut('ExampleAlias', DutType.Alias, "INT (0..100)") 

   # Instead of injecting the variables into the existing declaration, 
   # one can also just replace the complete declaration part, including the 
   # boilerplate code.
   example_dut_union = project.create_dut('ExampleUnion', DutType.Union)
   example_dut_union.textual_declaration.replace(ST_UNION_STR)

La siguiente función auxiliar incrementa la versión de compilación en la información del proyecto de un CODESYS proyecto.

def increment_build_version(project):
    """
    Increment build version in project info.
    """
    info = project.get_project_info()
    old_version = info.version
    info.version = (old_version.Major, old_version.Minor, old_version.Build + 1, 0)
    project.save()

La siguiente función crea primero una nueva rama y realiza cambios en esta rama y, a continuación, combina estos cambios de nuevo en la rama principal.

def copy_branch_and_merge(project):
    current_branch = project.git.branch_show_current()
    print("Current branch: ", current_branch.friendly_name)
    project, current_branch = project.git.branch_copy(current_branch, "new_branch", checkout=True)
    print("Current branch: ", current_branch.friendly_name)

    add_dut(project)
    project.git.commit_complete("Added DUT", "user", "mail@mail")

    increment_build_version(project)
    project.git.commit_complete("Incremented build version", "user", "mail@mail")

    project, current_branch = project.git.checkout("master")
    print("Current branch: ", current_branch.friendly_name)
    project, merge_result = project.git.merge("new_branch")
    print("Merged: ", merge_result.ToString())
    project.save()
    return project

Se ejecuta el siguiente script git clone para un repositorio Git remoto, realiza cambios en el proyecto y, a continuación, los envía al repositorio Git remoto (CopyBranchAndMerge.py).

def main():
    if projects.primary: 
       projects.primary.close()

    basepath = "C:\\CODESYS_Projects\\Git_Scripting_Tutorial\\"

    project_basepath = os.path.join(basepath, "projects\\")
    library_file_name = "ExampleLib1Cloned.library"

    remote_repo_basepath = os.path.join(basepath, "remotes\\")
    remote_repo_directory_name = "ExampleLib1RemoteRepo"
    remote_repo_path = os.path.join(remote_repo_basepath, remote_repo_directory_name)

    local_repo_basepath = os.path.join(basepath, "repos\\")
    local_repo_directory_name = "ExampleLib1LocalRepo"
    local_repo_path = os.path.join(local_repo_basepath, local_repo_directory_name)

    print("Clone project")
    project = clone_git_repository(project_basepath, library_file_name, remote_repo_path, local_repo_path)
    project = copy_branch_and_merge(project)
    project.git.push()
    project.save()
    project.git.de_init(cleanUpFileSystem=True)
    project.save()
    project.close()
    print("[Success] All done")

if __name__ == '__main__':
    main())

Creación de una biblioteca compilada

Se ejecuta el siguiente script git clone para un CODESYS biblioteca fuente desde un repositorio Git remoto y, a continuación, crea una biblioteca compilada a partir de ella (CreateCompiledLibrary.py).

import os

class CompileError(Exception):
    pass

def clone_git_repository(project_basepath, project_file_name, remote_repo_url_or_path, local_repo_path):
    update_flags = VersionUpdateFlags.UpdateAll | VersionUpdateFlags.SilentMode
    project = git.clone(project_basepath, project_file_name, remote_repo_url_or_path, local_repo_path, update_flags=update_flags)
    project.save()
    return project

def create_compiled_library(project):
    # requires the CODESYS Library Documentation Support Package!
    project.check_all_pool_objects()
    compile_result_message = system.get_messages(category='{97F48D64-A2A3-4856-B640-75C046E37EA9}')[-1]
    if "0 errors" in compile_result_message:
        project.save_as_compiled_library(destination_name=None)
    else:
        raise CompileError("Compile failed: " + compile_result_message)
    return project

basepath = "D:\\JiraTickets\\GIT-145\\"

project_basepath = os.path.join(basepath, "projects\\")

remote_repo_basepath = os.path.join(basepath, "remotes\\")
remote_repo_directory_name = "StringFunctions.git"
remote_repo_path = os.path.join(remote_repo_basepath, remote_repo_directory_name)

local_repo_basepath = os.path.join(basepath, "repos\\")
local_repo_path = os.path.join(local_repo_basepath, "StringFunctions.git")

print("Clone project")
project = clone_git_repository(project_basepath, "String Functions Cloned.library", remote_repo_path, local_repo_path)
project = create_compiled_library(project)
project.git.de_init(cleanUpFileSystem=True)
project.close()

print("[Success] All done")

Instalación de una biblioteca desde un repositorio remoto de Git

Se ejecuta el siguiente script git clone para un CODESYS biblioteca fuente desde un repositorio Git remoto e instala esta biblioteca en el repositorio actual CODESYS instancia (InstallLibrary.py).

import os

def clone_git_repository(project_directory_path, project_file_name, remote_repo_url_or_path, local_repo_path):
    update_flags = VersionUpdateFlags.UpdateAll | VersionUpdateFlags.SilentMode
    project = git.clone(project_directory_path, project_file_name, remote_repo_url_or_path, local_repo_path, update_flags=update_flags)
    project.save()
    return project

def install_library(project):
    library_repo = librarymanager.repositories[0]
    librarymanager.install_library(project.path, library_repo, True)

def main():
    if projects.primary:
        projects.primary.close()

     basepath = "C:\\CODESYS_Projects\\Git_Scripting_Tutorial\\"

    project_basepath = os.path.join(basepath, "projects\\")
    library_file_name = "ExampleLib1Cloned2.library"

    remote_repo_basepath = os.path.join(basepath, "remotes\\")
    remote_repo_directory_name = "ExampleLib1RemoteRepo"
    remote_repo_path = os.path.join(remote_repo_basepath, remote_repo_directory_name)

    local_repo_basepath = os.path.join(basepath, "repos\\")
    local_repo_directory_name = "ExampleLib1LocalRepo"
    local_repo_path = os.path.join(local_repo_basepath, local_repo_directory_name)

    print("Clone project")
    project = clone_git_repository(project_basepath, library_file_name, remote_repo_path, local_repo_path)

    print("Install library")
    install_library(project)
    project.git.de_init(cleanUpFileSystem=True)
    project.close()

    print("[Success] All done")

if __name__ == '__main__':
    main()

Salida de mensajes para operaciones de Git

Cuando se usa CODESYS Git, la mayoría de los comandos proporcionan resultados basados en texto. Cuando se ejecuta CODESYS en la línea de comandos, se genera automáticamente durante la ejecución de CODESYS Git comandos a través del controlador de script. Cuando se usa CODESYS Git en CODESYS Development System, las salidas también aparecen en la ventana de mensajes.

Structure of the messages: Git:<severity>: [<time>] <text>

In the user interface of CODESYS Git, the output is reduced to: [<time>] <text>

  • severity: categoría de mensaje. Las categorías van desde las puramente informativas hasta las de error crítico

  • time: Hora exacta del mensaje. Formato: HH:MM:SS

  • text: Contenido del mensaje. En el caso de los comandos estándar de Git, el contenido corresponde al comando de la línea de comandos que arrojaría el mismo resultado que la llamada realizada al controlador del script. CODESYS Git comandos que no corresponden a un comando estándar de Git (por ejemplo, Recuperar el proyecto del repositorio), el texto del mensaje explica la acción realizada.

Commands with multiple messages:

Para algunos comandos (por ejemplo, git log), la salida se divide en varios mensajes. En el caso de git log, cada confirmación que se muestra se muestra en un mensaje separado. En este caso, para dejar claro que estos mensajes forman parte del git log comando, se hace referencia al comando original en los mensajes.